﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private static readonly IPAddress GroupAddress = IPAddress.Parse("239.255.255.250"); // 定义组播地址
        private static readonly int GroupPort = 37020; // 定义发送组播时客户端的监听端口

        private static UdpClient udpClient;
        private static IPAddress localInterfaceAddress;
        private static readonly IPEndPoint GroupEndPoint = new IPEndPoint(GroupAddress, GroupPort);
        private static CancellationTokenSource cts;

        static string xmlString = @"<?xml version=""1.0"" encoding=""utf-8""?>
                            <Probe>
                            <Uuid>5EF20DD5-63D8-4449-9E70-81670167C86E</Uuid>
                            <Types>inquiry</Types>
                            </Probe>";



        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                // 自动获取并选择合适的本地网络接口
                localInterfaceAddress = GetBestLocalIPAddress();
                if (localInterfaceAddress == null)
                {
                    txtRevied.AppendText("\r\n未找到合适的本地网络接口");
                    return;
                }

                txtRevied.AppendText("\r\n选择的本地IP地址: " + localInterfaceAddress.ToString());

                // 初始化 UdpClient 实例并绑定到指定网络接口
                InitializeUdpClient();

                cts = new CancellationTokenSource();

                txtRevied.AppendText("\r\n开始从网卡 " + localInterfaceAddress.ToString() + " 发送和接收组播消息到 " + GroupAddress.ToString() + ":" + GroupPort.ToString());

                // 启动接收任务
                Task receiveTask = ReceiveMessagesAsync(txtRevied, ProcessReceivedMessage, cts.Token);
            }
            catch (OperationCanceledException)
            {
                // 正常取消操作
            }
            catch (Exception ex)
            {
                txtRevied.AppendText("程序发生错误: " + ex.Message);
            }
  
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            cts.Cancel();
            udpClient.Close();
        }



        // 添加用于处理接收到的消息的回调函数
        private void ProcessReceivedMessage(string message)
        {
            try
            {
                // 在这里添加您的数据解析逻辑
                // 示例：
                XDocument doc = XDocument.Parse(message);
                XElement root = doc.Root;
                string types = root.Element("Types").Value;
                if (types != "inquiry") return;

                string mac = root.Element("MAC").Value;
                string dev = root.Element("DeviceDescription").Value;
                string eth0_ip = root.Element("DeviceSN").Value;
                string eth1_ip = root.Element("IPv4Address").Value;
                string eth1_netMask = root.Element("IPv4SubnetMask").Value;
                string eth0_gateway = root.Element("IPv4Gateway").Value;
                string server_ip = root.Element("IPv6Address").Value;
                string server_port = root.Element("CommandPort").Value;
                string version = root.Element("SoftwareVersion").Value;


                bool deviceExists = false;
                foreach (DataGridViewRow row in this.dataGridView1.Rows)
                {
                    if (row.Cells[0].Value != null && row.Cells[0].Value.ToString() == mac &&
                        row.Cells[1].Value != null && row.Cells[1].Value.ToString() == dev &&
                        row.Cells[2].Value != null && row.Cells[2].Value.ToString() == eth0_ip &&
                        row.Cells[3].Value != null && row.Cells[3].Value.ToString() == eth1_ip &&
                        row.Cells[4].Value != null && row.Cells[4].Value.ToString() == eth1_netMask &&
                        row.Cells[5].Value != null && row.Cells[5].Value.ToString() == eth0_gateway &&
                        row.Cells[6].Value != null && row.Cells[6].Value.ToString() == server_ip &&
                        row.Cells[7].Value != null && row.Cells[7].Value.ToString() == server_port &&
                        row.Cells[8].Value != null && row.Cells[8].Value.ToString() == version)
                    {

                        deviceExists = true;
                        break;
                    }
                }

                if (deviceExists) return;
                // 只有当设备不存在时才添加新行
             
                // 确保线程安全地更新 UI
                if (dataGridView1.InvokeRequired)
                {
                    dataGridView1.Invoke(new Action(() =>
                    {
                        int index = dataGridView1.Rows.Add();
                        dataGridView1.Rows[index].Cells[0].Value = mac;
                        dataGridView1.Rows[index].Cells[1].Value = dev;
                        dataGridView1.Rows[index].Cells[2].Value = eth0_ip;
                        dataGridView1.Rows[index].Cells[3].Value = eth1_ip;
                        dataGridView1.Rows[index].Cells[4].Value = eth1_netMask;
                        dataGridView1.Rows[index].Cells[5].Value = eth0_gateway;
                        dataGridView1.Rows[index].Cells[6].Value = server_ip;
                        dataGridView1.Rows[index].Cells[7].Value = server_port;
                        dataGridView1.Rows[index].Cells[8].Value = version;
                    }));
                }
                else
                {
                    int index = dataGridView1.Rows.Add();
                    dataGridView1.Rows[index].Cells[0].Value = mac;
                    dataGridView1.Rows[index].Cells[1].Value = dev;
                    dataGridView1.Rows[index].Cells[2].Value = eth0_ip;
                    dataGridView1.Rows[index].Cells[3].Value = eth1_ip;
                    dataGridView1.Rows[index].Cells[4].Value = eth1_netMask;
                    dataGridView1.Rows[index].Cells[5].Value = eth0_gateway;
                    dataGridView1.Rows[index].Cells[6].Value = server_ip;
                    dataGridView1.Rows[index].Cells[7].Value = server_port;
                    dataGridView1.Rows[index].Cells[8].Value = version;
                }
            }
            catch (Exception ex)
            {
                txtRevied.AppendText("txtRevied.AppendText消息解析错误: " + ex.Message);
            }
        }

        private  void InitializeUdpClient()
        {
            // 创建并配置 UdpClient
            udpClient = new UdpClient();

            // 允许与其他套接字共用地址
            udpClient.EnableBroadcast = true;
            udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

            // 绑定到指定的本地接口地址和端口
            udpClient.Client.Bind(new IPEndPoint(localInterfaceAddress, GroupPort));

            // 设置组播选项，指定使用哪个网络接口发送和接收组播数据
            udpClient.JoinMulticastGroup(GroupAddress, localInterfaceAddress);

            txtRevied.AppendText("\r\nUdpClient已初始化，绑定到本地接口: " + localInterfaceAddress.ToString() + ":" + GroupPort.ToString());
        }

        /// <summary>
        /// 自动获取最佳的本地IP地址
        /// </summary>
        /// <returns>本地IP地址</returns>
        private  IPAddress GetBestLocalIPAddress()
        {
            try
            {
                // 获取所有网络接口
                NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

                foreach (NetworkInterface ni in networkInterfaces)
                {
                    // 只考虑运行中的网络接口
                    if (ni.OperationalStatus != OperationalStatus.Up)
                        continue;

                    // 只考虑以太网或无线网络接口
                    if (ni.NetworkInterfaceType != NetworkInterfaceType.Ethernet &&
                        ni.NetworkInterfaceType != NetworkInterfaceType.Wireless80211)
                        continue;

                    IPInterfaceProperties properties = ni.GetIPProperties();

                    // 跳过回环接口
                    if (properties.GatewayAddresses.Count == 0)
                        continue;

                    foreach (UnicastIPAddressInformation ip in properties.UnicastAddresses)
                    {
                        // 只考虑IPv4地址
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            // 排除回环地址
                            if (!IPAddress.IsLoopback(ip.Address))
                            {
                                return ip.Address;
                            }
                        }
                    }
                }

                // 如果没有找到合适的网络接口，尝试使用默认方法获取本地IP
                IPAddress[] localIPs = Dns.GetHostEntry(Dns.GetHostName()).AddressList
                    .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(ip))
                    .ToArray();

                return localIPs.Length > 0 ? localIPs[0] : null;
            }
            catch (Exception ex)
            {
                //txtRevied.AppendText("\r\n获取本地IP地址时出错: " + ex.Message);
                return null;
            }
        }
        private void ExportToCSV(DataGridView dataGridView)
        {
            using (SaveFileDialog saveFileDialog = new SaveFileDialog()
            {
                Filter = "CSV文件|*.csv",
                Title = "保存CSV文件"
            })
            {
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    StringBuilder sb = new StringBuilder();

                    // 导出列标题
                    for (int i = 0; i < dataGridView.Columns.Count; i++)
                    {
                        sb.Append(dataGridView.Columns[i].HeaderText);
                        sb.Append(i == dataGridView.Columns.Count - 1 ? "\n" : ",");
                    }

                    // 导出数据
                    for (int i = 0; i < dataGridView.Rows.Count; i++)
                    {
                        for (int j = 0; j < dataGridView.Columns.Count; j++)
                        {
                            if (dataGridView.Rows[i].Cells[j].Value != null)
                            {
                                string value = dataGridView.Rows[i].Cells[j].Value.ToString();
                                // 处理包含逗号或引号的值
                                if (value.Contains(",") || value.Contains("\""))
                                {
                                    value = "\"" + value.Replace("\"", "\"\"") + "\"";
                                }
                                sb.Append(value);
                            }
                            sb.Append(j == dataGridView.Columns.Count - 1 ? "\n" : ",");
                        }
                    }

                    File.WriteAllText(saveFileDialog.FileName, sb.ToString(), Encoding.UTF8);
                    MessageBox.Show("导出成功！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }
        private  void Send(string message)
        {
            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(message);
                udpClient.Send(bytes, bytes.Length, GroupEndPoint);
                txtRevied.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "] 消息已从 " + localInterfaceAddress.ToString() + " 发送: " + message);
            }
            catch (SocketException socketEx)
            {
                //showMessage("网络异常: " + socketEx.Message + " (错误代码: " + socketEx.ErrorCode.ToString() + ")");
            }
            catch (Exception ex)
            {
                //showMessage("发送消息时发生错误: " + ex.Message);
            }
        }

        private static async Task ReceiveMessagesAsync(TextBox txtRevied, Action<string> onMessageReceived, CancellationToken cancellationToken)
        {
            const string TimeFormat = "HH:mm:ss";

            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    // 异步接收数据
                    UdpReceiveResult result = await udpClient.ReceiveAsync().WithCancellation(cancellationToken);

                    string receivedMessage = Encoding.UTF8.GetString(result.Buffer);
                    IPEndPoint remoteEndPoint = result.RemoteEndPoint;

                    // 过滤自己发送的消息
                    if (remoteEndPoint.Address.Equals(localInterfaceAddress) && remoteEndPoint.Port == GroupPort)
                    {
                        // 这是自己发送的消息，跳过处理
                        continue;
                    }

                    // 使用 StringBuilder 替代 string.Format
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine();
                    sb.AppendFormat("[{0}] 收到来自 {1} 的消息: {2}",
                        DateTime.Now.ToString(TimeFormat),
                        remoteEndPoint,
                        receivedMessage);

                    string message = sb.ToString();

                    // 确保线程安全地更新 UI
                    if (txtRevied.InvokeRequired)
                    {
                        txtRevied.Invoke(new Action(() => txtRevied.AppendText(message + Environment.NewLine)));
                    }
                    else
                    {
                        txtRevied.AppendText(message + Environment.NewLine);
                    }

                    try
                    {
                        onMessageReceived.Invoke(receivedMessage);
                    }
                    catch (Exception ex)
                    {
                        // 防止回调函数中的异常影响主接收流程
                        // Console.WriteLine("回调函数执行错误: " + ex.Message);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // 正常取消操作
            }
            catch (ObjectDisposedException)
            {
                // UdpClient 已被释放
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode != SocketError.Interrupted)
                {
                    Console.WriteLine("接收消息时发生网络错误: " + ex.Message);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("接收消息时发生错误: " + ex.Message);
            }
        }
         static string ConvertToIPv6CompatibleFormat(string ipv4Address)
        {
            // 将IPv4地址解析为IPAddress对象
            IPAddress address = IPAddress.Parse(ipv4Address);
        
            // 获取IPv4地址的字节表示
            byte[] bytes = address.GetAddressBytes();
        
            // 构造IPv6兼容格式的字符串
            string ipv6Format = string.Format("{0}:{1}:{2}:{3}:0:0:0:0",
                                         bytes[0], bytes[1], bytes[2], bytes[3]);
        
            return ipv6Format;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            Send(xmlString);
        }
        public static bool IsValidIP(string ip)
        {
            return Regex.IsMatch(ip, @"^(\d{1,3}\.){3}\d{1,3}$") && ip.Split('.').All(segment => int.Parse(segment) < 256);
        }
        private void btnConfig_Click(object sender, EventArgs e)
        {

            string mac = txtconfigMac.Text.Trim();
            string Eth1Ip = txtconfigEth1Ip.Text.Trim();
            string server_ip = txtServerip.Text.Trim();
            string Eth1netmask = txtconfigEth1netmask.Text.Trim();
            string Eth1gateway = txtconfigEth1gatewa.Text.Trim();
            if(mac==string.Empty)
            {
                MessageBox.Show("请选中需要修改的设备");
                return;
            }
            if (IsValidIP(Eth1Ip) == false)
            {
                MessageBox.Show("请输入正确ip地址");
                return;
            }
            int server_port;
            int.TryParse(txtServerport.Text.Trim(), out server_port);
            if(server_port ==0)
            {
                MessageBox.Show("请输入正确服务器端口");
                return;
            }
            if (IsValidIP(server_ip) == false)
            {
                MessageBox.Show("请输入正确服务器ip地址");
                return;
            }
            if (IsValidIP(Eth1netmask) == false)
            {
                MessageBox.Show("请输入正确掩码");
                return;
            }
            if (IsValidIP(Eth1gateway) == false)
            {
                MessageBox.Show("请输入正确的网关");
                return;
            }
            // 创建生成器实例并传入所有参数
            var generator = new ProbeXmlGenerator(
                uuid: Guid.Parse("5EF20DD5-63D8-4449-9E70-81670167C86E"),
                types: "update",
                pwErrorParse: true,
                mac: mac,
                password: "ucX5kMVmteIXwDFcJVkkuq3+kKpnbLDheIrhzYFQ0G4Z77zLY3RHlx9snjMc7QIDb+ZDPniphQy4tN+YQzrUQg==",
                passwordSalt: true,
                ipv4Address: Eth1Ip,
                commandPort: server_port,
                ipv4SubnetMask: Eth1netmask,
                ipv4Gateway: Eth1gateway,
                ipv6Address: ConvertToIPv6CompatibleFormat(server_ip),
                ipv6Gateway: "::",
                ipv6MaskLen: 64,
                dhcp: false,
                httpPort: 8089
            );

            // 生成XML字符串
            string xml = generator.GenerateXml();
            Send(xml);
            dataGridView1.Rows.Clear();
            Thread.Sleep(200);
            Send(xmlString);
        }

        private void dataGridView1_SelectionChanged(object sender, EventArgs e)
        {
            try
            {
                if (dataGridView1.CurrentRow == null) return;
                int index = dataGridView1.CurrentRow.Index; //获取选中行的行号
                txtconfigMac.Text = dataGridView1.Rows[index].Cells[0].Value.ToString();
                txtconfigDEV.Text = dataGridView1.Rows[index].Cells[1].Value.ToString();
                txtconfigEth0IP.Text = dataGridView1.Rows[index].Cells[2].Value.ToString();
                txtconfigEth1Ip.Text = dataGridView1.Rows[index].Cells[3].Value.ToString();
                txtconfigEth1netmask.Text = dataGridView1.Rows[index].Cells[4].Value.ToString();
                txtconfigEth1gatewa.Text = dataGridView1.Rows[index].Cells[5].Value.ToString();
                txtServerip.Text = dataGridView1.Rows[index].Cells[6].Value.ToString();
                txtServerport.Text = dataGridView1.Rows[index].Cells[7].Value.ToString();
                txtSorfVer.Text = dataGridView1.Rows[index].Cells[8].Value.ToString();

            }
            catch (Exception ex)
            {
                Console.WriteLine("dataGridView1_SelectionChanged 错误: " + ex.Message);
            }
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            //dataGridView1.Columns.Clear();
            dataGridView1.Rows.Clear();
            txtRevied.Text = string.Empty;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            int index = dataGridView1.Rows.Add();
            dataGridView1.Rows[index].Cells[0].Value = txtconfigMac.Text;
            dataGridView1.Rows[index].Cells[1].Value = txtconfigMac.Text;
            dataGridView1.Rows[index].Cells[2].Value = txtconfigMac.Text;
            dataGridView1.Rows[index].Cells[3].Value = txtconfigMac.Text;
            dataGridView1.Rows[index].Cells[4].Value = txtconfigMac.Text;
            dataGridView1.Rows[index].Cells[5].Value = txtconfigMac.Text;
            dataGridView1.Rows[index].Cells[6].Value = txtconfigMac.Text;
            dataGridView1.Rows[index].Cells[7].Value = txtconfigMac.Text;
            dataGridView1.Rows[index].Cells[8].Value = txtconfigMac.Text;
        }

        private void btnDataOut_Click(object sender, EventArgs e)
        {
            ExportToCSV(dataGridView1); // 或调用其他导出方法
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            tsslDateTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }
    }

    // 扩展方法，为 Task 添加 WithCancellation 支持
    public static class TaskExtensions
    {
        public static async Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource<bool>();
            using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
            {
                if (task != await Task.WhenAny(task, tcs.Task))
                {
                    throw new OperationCanceledException(cancellationToken);
                }
            }
            return await task;
        }
    }

    public class ProbeXmlGenerator
    {
        public Guid Uuid { get; set; }
        public string Types { get; set; }
        public bool PWErrorParse { get; set; }
        public string MAC { get; set; }
        public string Password { get; set; }
        public bool PasswordSalt { get; set; }
        public string IPv4Address { get; set; }
        public int CommandPort { get; set; }
        public string IPv4SubnetMask { get; set; }
        public string IPv4Gateway { get; set; }
        public string IPv6Address { get; set; }
        public string IPv6Gateway { get; set; }
        public int IPv6MaskLen { get; set; }
        public bool DHCP { get; set; }
        public int HttpPort { get; set; }

        public ProbeXmlGenerator(
            Guid uuid,
            string types,
            bool pwErrorParse,
            string mac,
            string password,
            bool passwordSalt,
            string ipv4Address,
            int commandPort,
            string ipv4SubnetMask,
            string ipv4Gateway,
            string ipv6Address,
            string ipv6Gateway,
            int ipv6MaskLen,
            bool dhcp,
            int httpPort)
        {
            Uuid = uuid;
            Types = types;
            PWErrorParse = pwErrorParse;
            MAC = mac;
            Password = password;
            PasswordSalt = passwordSalt;
            IPv4Address = ipv4Address;
            CommandPort = commandPort;
            IPv4SubnetMask = ipv4SubnetMask;
            IPv4Gateway = ipv4Gateway;
            IPv6Address = ipv6Address;
            IPv6Gateway = ipv6Gateway;
            IPv6MaskLen = ipv6MaskLen;
            DHCP = dhcp;
            HttpPort = httpPort;
        }

        public string GenerateXml()
        {
            // 创建XML文档
            XDocument xmlDoc = new XDocument(
                new XDeclaration("1.0", "utf-8", null),
                new XElement("Probe",
                    new XElement("Uuid", Uuid.ToString("D").ToUpper()),
                    new XElement("Types", Types),
                    new XElement("PWErrorParse", PWErrorParse.ToString().ToLower()),
                    new XElement("MAC", MAC),
                    new XElement("Password",
                        new XAttribute("bSalt", PasswordSalt.ToString().ToLower()),
                        Password
                    ),
                    new XElement("IPv4Address", IPv4Address),
                    new XElement("CommandPort", CommandPort),
                    new XElement("IPv4SubnetMask", IPv4SubnetMask),
                    new XElement("IPv4Gateway", IPv4Gateway),
                    new XElement("IPv6Address", IPv6Address),
                    new XElement("IPv6Gateway", IPv6Gateway),
                    new XElement("IPv6MaskLen", IPv6MaskLen),
                    new XElement("DHCP", DHCP.ToString().ToLower()),
                    new XElement("HttpPort", HttpPort)
                )
            );

            // 转换为字符串（保留XML声明）
            StringBuilder sb = new StringBuilder();
            using (var writer = new System.IO.StringWriter(sb))
            {
                xmlDoc.Save(writer);
            }

            return sb.ToString();
        }
    }
}